#include "stdafx.h" 

#include "EngineTests.h"

using namespace System;
using namespace CzechMoveGen;

void TestStartUpPosition()
{
	int logId = LogInit("c:\\startup.txt");

	BitBoard bb;
	SetStartUpPositionBitBoard(&bb);

	LogBitBoard(logId, bb);

	LogClose(logId);
}


 // BOARD EVALUATION
///////////////////////////////////////////////////////////////////////////////////////////////////////////

// evaluation tables
///////////////////////////////////////////////////////////
int dwWhitePosTable[ GAMEBOARD_SIZE ] = { 0,0,0,0,0,
											1,1,1,1,	0,
											2,2,2,2,
											3,3,3,3,	0,
											4,4,4,4,
											5,5,5,5,	0,
											6,6,6,6,	
											7,7,7,7,	0,
											8,8,8,8,
											0,0,0,0,0,0,0 };

int dwBlackPosTable[ GAMEBOARD_SIZE ] = { 0,0,0,0,0,
											8,8,8,8,	0,
											7,7,7,7,
											6,6,6,6,	0,
											5,5,5,5,
											4,4,4,4,	0,
											3,3,3,3,	
											2,2,2,2,	0,
											1,1,1,1,
											0,0,0,0,0,0,0 };



 // Basic simple evaluation function
/////////////////////////////////////////////////////////////////

int EvaluateGameBoard(TGameBoard board, bool bForWhite)
{
	register int iWhiteValue = 0;
	register int iBlackValue = 0;
	register bool bWhiteFigureFound = false;
	register bool bBlackFigureFound = false;


	for(int i = 0; i < GAMEBOARD_SIZE; i++)
	{
		register BYTE dwField = board[ i ];
		if( dwField == BORDER )
			continue;
		if( IS_EMPTY( dwField ) ) 
			continue;

		if( IS_King( dwField ) )
		{
			if(IS_WHITEFIGURE( dwField ))
			{
				iWhiteValue +=	King_VALUE;
				bWhiteFigureFound = true;
			}
			else
			{
				iBlackValue +=	King_VALUE;
				bBlackFigureFound = true;
			}
		}
		else
		{
			if(IS_WHITEFIGURE( dwField ))
			{
				iWhiteValue += MAN_VALUE + dwWhitePosTable[i];
				bWhiteFigureFound = true;
			}
			else
			{
				iBlackValue += MAN_VALUE + dwBlackPosTable[i];
				bBlackFigureFound = true;
			}			
		}
	} // for

	if(bWhiteFigureFound == false)
		iBlackValue = GAME_WIN;
	if(bBlackFigureFound == false)
		iWhiteValue = GAME_WIN;

	return bForWhite ? iWhiteValue - iBlackValue : iBlackValue - iWhiteValue;
}

 // SEARCH ALGORITHM
////////////////////////////////////////////////////////////////////////////////////////////////

TGameBoard oldBoard;
BitBoard bitBoard;
int bbLogId;


int Negamax(int depth , TSingleMove* pReturnedBestMove, bool* pbJump, BitBoardMove* pbbMove , bool bWhite)
{
	// return evaluation
	if(depth == 0)
		return EvaluateGameBoard(oldBoard, bWhite);


	// generate old board moves
	SMoveAnalysis* pMoveAnalysis = new SMoveAnalysis;
	GenerateMoves( oldBoard, pMoveAnalysis, bWhite );
	BYTE dwCount = pMoveAnalysis->GetCount();
	bool bJumps = pMoveAnalysis->HasJumps();
	if( dwCount == 0)
	{
		delete pMoveAnalysis;
		return GAME_LOSS;
	}

	BitBoardMove bitMoves[150];


	// generate bitboard moves
	int bbCount = GenerateBitBoardMoves(&bitBoard, bWhite, bitMoves);
	if(dwCount != bbCount)
	{
		LogMessage(bbLogId, "Nesedi pocty tahu.\n");
		LogBitBoard(bbLogId, bitBoard);
	}

	// porovnej tahy
	int moveAssoc[150];
	for(int i = 0; i < bbCount; i++)
		moveAssoc[i] = -1;

	for(int i = 0; i < bbCount; i++)
	{
		bool oFound = false;
		for(int j = 0; j < dwCount; j++)
		{
			TSingleMove cmpMove;
			pMoveAnalysis->GetMove(j, &cmpMove);

			// fill in the number of moves
			ZOBRIST_KEY keyDummy = 0;
			DoMove(oldBoard, &cmpMove, bJumps, keyDummy);
			UndoMove(oldBoard, &cmpMove, bJumps, keyDummy);

			if(CheckMove(oldBoard, &cmpMove, bitMoves[i], bJumps) == true)
			{
				if(moveAssoc[j] < 0)
				{
					oFound = true;
					moveAssoc[j] = i;
					break;
				}
			}
		}

		if(oFound == false)
		{
			LogMessage(bbLogId, "Nenalezen tah:\n\n");
			LogBitBoard(bbLogId, bitBoard);
			LogBitBoard(bbLogId, bitMoves[i]);
			throw new char('e');
		}
	} // for


	// iterate through moves
	TSingleMove moveToDo;
	TSingleMove bestMove;
	BitBoardMove bbBestMove;
	int bestResult = GAME_LOSS;
	for(BYTE i = 0; i < dwCount; i++)
	{
		pMoveAnalysis->GetMove(i, &moveToDo);

		// do move
		ZOBRIST_KEY keyDummy = 0;
		DoMove(oldBoard, &moveToDo, bJumps, keyDummy);

		ToggleMove(&bitBoard, &bitMoves[moveAssoc[i]]);

		// call next level
		int result = -Negamax(depth - 1, NULL, NULL, NULL , ! bWhite );

		// first move has to be undone to clear additional info added to moveToDo variable
		// undo move
		UndoMove(oldBoard, &moveToDo, bJumps, keyDummy);

		ToggleMove(&bitBoard, &bitMoves[moveAssoc[i]]);


		// compare result
		if(result >= bestResult)
		{
			memcpy(&bestMove, &moveToDo, sizeof(TSingleMove));
			memcpy(&bbBestMove, &bitMoves[moveAssoc[i]], sizeof(BitBoardMove));
			bestResult = result;
		} // if

	} // for

	if(pReturnedBestMove != NULL)
	{
		memcpy(pReturnedBestMove, &bestMove, sizeof(TSingleMove));
		if(pbJump != NULL)
			*pbJump = bJumps;
		if(pbbMove)
			memcpy(pbbMove, &bbBestMove, sizeof(BitBoardMove));

//		iSearchDepth = iMaxDepth = depth;
	}

	delete pMoveAnalysis;

	return bestResult;
}


bool BitBoardTest1()
{
	bbLogId = LogInit("c:\\bitboard.txt");

	SetStartUpPositionBitBoard(&bitBoard);
	SetStartUpPositionGameBoard(oldBoard);

	bool oError = true;

	try
	{
		Negamax(6, NULL, NULL, NULL, true);

		oError = false;
	}
	catch(...)
	{
	}


	LogClose(bbLogId);

	return oError;
}

bool BitBoardMatchTest()
{
	bbLogId = LogInit("c:\\matchresult.txt");

	SetStartUpPositionBitBoard(&bitBoard);
	SetStartUpPositionGameBoard(oldBoard);

	bool oError = true;

	try
	{
		bool bWhite = true;
		for(int i = 0; i < 100; i++)
		{
			Console::WriteLine(L"Move: {0}", i);

			// compute move
			bool bJump;
			TSingleMove oldMove;
			BitBoardMove bbMove;		
			Negamax(6, &oldMove, &bJump, &bbMove, bWhite);

			// log move
			LOG_MSG(bbLogId, "Move: %d\n", i);
			LogBitBoard(bbLogId, bitBoard);
			LogBitBoard(bbLogId, bbMove);

			// do move
			ZOBRIST_KEY keyDummy = 0;
			DoMove(oldBoard, &oldMove, bJump, keyDummy);
			ToggleMove(&bitBoard, &bbMove);

			bWhite = ! bWhite;
		}


		oError = false;
	}
	catch(...)
	{
	}


	LogClose(bbLogId);

	return oError;
}

